
#include <scenewriter.h>
#include <QFile>


SceneWriter::SceneWriter(ceEngine* engine)
  : _engine(engine)
{
}

void SceneWriter::WriteNode(ceNode *node, const QString &filename)
{
  QFile file (filename);
  if (!file.open(QIODevice::WriteOnly))
    {
      return;
    }

  QDomDocument doc ("CrimsonCore-Object");

  QDomElement nodeElement = CreateNodeElement(doc, node);
  if (!nodeElement.isNull())
    {
      doc.appendChild(nodeElement);
    }

  file.write(doc.toByteArray(4));
  file.close();
}

QDomElement SceneWriter::CreateNodeElement(QDomDocument doc, ceNode *node)
{
  switch (node->GetType())
    {
    case NT_GroupNode:
      return CreateGroupNodeElement(doc, static_cast<GroupNode*>(node));
    case NT_EntityNode:
      return CreateEntityNodeElement(doc, static_cast<EntityNode*>(node));
    case NT_LODNode:
      return CreateLODNodeElement(doc, static_cast<LODNode*>(node));
    }
  return QDomElement ();
}

QDomElement SceneWriter::CreateGroupNodeElement(QDomDocument doc, GroupNode *group)
{
  QDomElement groupElement = doc.createElement("node");
  groupElement.setAttribute("type", "group");
  groupElement.setAttribute("name", group->GetName().c_str());

  NodeList& list = group->GetChildren();
  NodeListIterator it;
  for (it = list.begin(); it != list.end(); ++it)
    {
      ceNode* node = *it;
      QDomElement nodeElement = CreateNodeElement (doc, node);
      if (!nodeElement.isNull())
        {
          groupElement.appendChild(nodeElement);
        }
    }

  return groupElement;
}

QDomElement SceneWriter::CreateLODNodeElement(QDomDocument doc, LODNode *lod)
{
  QDomElement lodElement  = doc.createElement("node");
  lodElement.setAttribute("type", "lod");
  lodElement.setAttribute("name", lod->GetName().c_str());

  unsigned levels = lod->Get().GetNumberOfLevels();
  for (unsigned i=0; i<levels; ++i)
    {
      ceNode* node = lod->Get().Get(i);
      if (!node)
        {
          continue;
        }

      QDomElement nodeElement = CreateNodeElement(doc, node);
      if (!nodeElement.isNull())
        {
          lodElement.appendChild(nodeElement);
        }

    }

  return lodElement;
}

QDomElement SceneWriter::CreateEntityNodeElement(QDomDocument doc, EntityNode *entity)
{
  QDomElement entityElement = doc.createElement("node");
  entityElement.setAttribute("type", "entity");
  entityElement.setAttribute("name", entity->GetName().c_str());

  QDomElement transformationElement = doc.createElement("transformation");
  transformationElement.appendChild(CreateMatrix4f(doc, entity->GetMatrix()));
  entityElement.appendChild(transformationElement);

  entityElement.appendChild(CreateShadowElement(doc, entity));

  QDomElement groupElement = CreateGeometryElement(doc, static_cast<Geometry*>(entity->GetGeometry()));
  if (!groupElement.isNull())
    {
      entityElement.appendChild(groupElement);
    }

  return entityElement;
}

QDomElement SceneWriter::CreateGeometryElement(QDomDocument doc, Geometry *geometry)
{
  if (!geometry) return QDomElement ();

  QDomElement geometryElement = doc.createElement("geometry");

  switch (geometry->GetMetaMeshType())
    {
    case MT_Static:
      {
        QDomElement staticMesh = doc.createElement("staticmesh");
        QDomElement mesh = doc.createElement("mesh");
        mesh.setAttribute("filename", geometry->GetMetaMeshFilename());
        staticMesh.appendChild(mesh);
        geometryElement.appendChild(staticMesh);
      }
      break;
    default:
      return QDomElement();
    }

  QDomElement materialElement = doc.createElement("material");


  QString name = geometry->GetMetaMaterialName();
  if (name.length() == 0)
    {
      name = "Default";
    }
  materialElement.appendChild(doc.createTextNode(name));
  geometryElement.appendChild(materialElement);

  return geometryElement;
}

QDomElement SceneWriter::CreateMatrix4f(QDomDocument doc, const ceMatrix4f &matrix)
{
  QDomElement matrixElement = doc.createElement("matrix");

  QDomElement row0 = doc.createElement("row");
  row0.setAttribute("m00", matrix._00);
  row0.setAttribute("m01", matrix._01);
  row0.setAttribute("m02", matrix._02);
  row0.setAttribute("m03", matrix._03);
  matrixElement.appendChild(row0);

  QDomElement row1 = doc.createElement("row");
  row1.setAttribute("m10", matrix._10);
  row1.setAttribute("m11", matrix._11);
  row1.setAttribute("m12", matrix._12);
  row1.setAttribute("m13", matrix._13);
  matrixElement.appendChild(row1);

  QDomElement row2 = doc.createElement("row");
  row2.setAttribute("m20", matrix._20);
  row2.setAttribute("m21", matrix._21);
  row2.setAttribute("m22", matrix._22);
  row2.setAttribute("m23", matrix._23);
  matrixElement.appendChild(row2);

  QDomElement row3 = doc.createElement("row");
  row3.setAttribute("m30", matrix._30);
  row3.setAttribute("m31", matrix._31);
  row3.setAttribute("m32", matrix._32);
  row3.setAttribute("m33", matrix._33);
  matrixElement.appendChild(row3);

  return matrixElement;
}

QDomElement SceneWriter::CreateShadowElement(QDomDocument doc, EntityNode *entity)
{
  QDomElement shadowElement = doc.createElement("shadow");

  if (entity->CastsShadow())
    {
      shadowElement.setAttribute("castShadow", "true");
    }
  else
    {
      shadowElement.setAttribute("castShadow", "false");
    }

  return shadowElement;
}

